package com.wthink.card.Thread;

import android.content.Context;
import android.os.Handler;
import android.util.Log;

import com.wthink.card.ShdThread;
import com.wthink.hzgj.util.TcpHelp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.ByteBuffer;
import java.security.InvalidParameterException;

public class SocketFrameProcThread extends ShdThread {

	public static StringBuilder mStrCardId = new StringBuilder();
	private static final String THIS_FILE = "SocketFrameProcThread";
	private static SocketFrameProcThread _instance;
	private Socket client;
	private static InputStream vcaIS;
	private static OutputStream vcaOS;

	public SocketFrameProcThread(Context ctx, Handler h){
		super( ctx, SocketFrameProcThread.THIS_FILE, h);
	}

	public SocketFrameProcThread(Context ctx){
		super( ctx, SocketFrameProcThread.THIS_FILE);
	}

	public static synchronized SocketFrameProcThread getInstance(Context ctx, Handler h) {
		if(_instance == null) {
			_instance = new SocketFrameProcThread( ctx, h);
		}
		return _instance;
	}

	public static synchronized SocketFrameProcThread getInstance(Context ctx) {
		if(_instance == null) {
			_instance = new SocketFrameProcThread( ctx);
		}
		return _instance;
	}
	public static synchronized void setInstance(Context ctx) {
		if(_instance != null) {
			_instance = null;
		}
	}

	public synchronized int sendData(byte[] data, int dataLen) {

		if (vcaOS == null) {
			return ER_SYSTEM_EXCEPTION;
		}
		try {
			vcaOS.write(data, 0, dataLen);
		} catch (IOException e) {
			e.printStackTrace();
			return ER_SYSTEM_EXCEPTION;
		}

		return 0;
	}

	/**
	 * 透传方法
	 * type 协议类型
	 * data 数据
	 * datalen 数据长度
	 * drivcetype 设备类型
	 */
	public int SendToMainBoardNormalFrm(int type, byte[] data, int datalen,int drivceType) {
		ByteBuffer out = ByteBuffer.allocate(10 + datalen);
		packBoardNormalClient(type, data, datalen, out, drivceType);
		return sendData(out.array(), out.position());
	}

	public int SendToMainboardOriFrm(byte[] data, int datalen){
		return sendData(data, datalen);
	}

	public synchronized void closeSocketPort() {
		if (vcaOS != null) {
			try {
				vcaOS.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			vcaOS = null;
		}

		if (vcaIS != null) {
			try {
				vcaIS.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			vcaIS = null;
		}

		if (client != null) {
			try {
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			client = null;
		}
	}

	/**
	 * 函数名：ClientConnect 用途 ：连接服务器 参数 ：无 返回值：无
	 **/
	public void ClientConnect() {

		boolean result = false;

		try {
			/*client = new Socket();
			String ip = InetAddress.getLocalHost().getHostAddress();
			SocketAddress remoteAddr = new InetSocketAddress(ip, 31001);
			client.connect(remoteAddr, 8000);	//连接8s超时/*/
			client = TcpHelp.INSTANCE.getClient();
			if (client == null || !client.isConnected()) {
				TcpHelp.INSTANCE.reconnect(System.currentTimeMillis());
				Log.i("debug", "断线重连");
				client = TcpHelp.INSTANCE.getClient();
			}

			if (vcaIS == null && client.isConnected()) {
				vcaIS = client.getInputStream();
			}
			if (vcaOS == null && client.isConnected()) {
				vcaOS = client.getOutputStream();
			}
			// 设置 socket 读取数据流的超时时间
			if (client.isClosed()) {
				return;
			}
			client.setSoTimeout(10000);
			// 发送数据包，默认为 false，即客户端发送数据采用 Nagle 算法
			// 但是对于实时交互性高的程序，建议其改为 true，即关闭 Nagle
			// 算法，客户端每发送一次数据，无论数据包大小都会将这些数据发送出去
			client.setTcpNoDelay(true);
			// 设置客户端 socket 关闭时，close() 方法起作用时延迟 10 秒关闭，如果 10 秒内尽量将未发送的数据包发送出去
			client.setSoLinger(true, 0);
			// 防止服务器端无效时，客户端长时间处于连接状态
			client.setKeepAlive(true);
			result = true;
		} catch (SocketTimeoutException e) {
			e.printStackTrace();
		} catch (ConnectException e) { // 服务器没开
			e.printStackTrace();
		} catch (IOException e) { // 连接超时
			e.printStackTrace();
		}

		// 连接结果通知		//打开功放和音频通道
		if(result){
			ByteBuffer frameBuf = ByteBuffer.allocate(4);
			/* == ic卡模块初始化 == */
			frameBuf.clear();
			frameBuf.put((byte) 0x00);
			frameBuf.put((byte) 0x00);
			frameBuf.put((byte) 0x00);
			SendToMainBoardNormalFrm(0x01, frameBuf.array(), 3, 2);
			/* == 通道切换 ==  P1001 喇叭固定为tts通道*/
			frameBuf.clear();
			frameBuf.put((byte) 5);
			SendToMainBoardNormalFrm(0x04, frameBuf.array(), 1, 1);
		}
	}

	public static boolean createDir(String destDirName) {
		File dir = new File(destDirName);
		if (dir.exists()) {
			return true;
		}
		if (!destDirName.endsWith(File.separator)) {
			destDirName = destDirName + File.separator;
		}
		//创建目录
		if (dir.mkdirs()) {
			return true;
		} else {
			return false;
		}
	}

	public void run() {
		try {
			int rc;
			int rc2;
			ClientConnect();
			while (!isInterrupted()) {
				rc = readAndParseShdFrameTcp(vcaIS);
				if (rc == NR_READY_FOR_PROCESS) { // process new shed frame bundle
					rc2 = processShdFrameBundleTcp();
					if (rc2 < 0 && rc2 != ER_WRONG_FRAME) {
						vcaLastError = rc2;
					}
				} else if (rc <= 0 && rc != ER_WRONG_FRAME) { // error
					Log.i("debug", "re connect!");
					vcaLastError = rc;
					closeSocketPort();
					ClientConnect();
					Thread.sleep(10000);
				}
				Thread.sleep(200);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (InvalidParameterException e) {
			e.printStackTrace();
		} finally {
			closeSocketPort();
		}
	}
}
